#pragma once
#include "Allocator.h"
#include "Iterator.h"
#include "Trait.h"
#include "Algorithm.h"
namespace mini
{
	struct _Loop_node_base
	{
		_Loop_node_base* pNext = nullptr;
	};

	template <typename T>
	struct _Loop_node : public _Loop_node_base
	{
		T Data;
	};


	struct _Loop_iterator_base
	{
		typedef size_t						size_type;
		typedef ptrdiff_t					difference_type;
		typedef forwardIteratorTag			iterator_category;

		_Loop_iterator_base(_Loop_node_base* __x) : mpBaseNode(__x) {}
		_Loop_iterator_base() {}

		void increase()
		{
			mpBaseNode = mpBaseNode->pNext;
		}

		bool operator==(const _Loop_iterator_base& __x) const
		{
			return mpBaseNode == __x.mpBaseNode;
		}

		bool operator!=(const _Loop_iterator_base& __x) const
		{
			return mpBaseNode != __x.mpBaseNode;
		}

		_Loop_node_base* mpBaseNode = nullptr;

	};


	template<class T, class _Ref, class _Ptr>
	struct _Loop_iterator : public _Loop_iterator_base
	{
		typedef _Loop_iterator<T, T&, T*>             iterator;
		typedef _Loop_iterator<T, const T&, const T*> const_iterator;
		typedef _Loop_iterator<T, _Ref, _Ptr>         self;

		typedef T value_type;
		typedef _Ptr pointer;
		typedef _Ref reference;
		typedef _Loop_node<T> _Node;

		_Loop_iterator(_Node* __x) : _Loop_iterator_base(__x) {}
		_Loop_iterator() {}
		_Loop_iterator(const iterator& __x) : _Loop_iterator_base(__x.mpBaseNode) {}

		pointer operator->() const
		{
			return &(operator*());
		}

		reference operator*() const
		{
			return ((_Node*)mpBaseNode)->Data;
		}

		self& operator++()
		{
			this->increase();
			return *this;
		}
		self operator++(int)
		{
			self __tmp = *this;
			this->increase();
			return __tmp;
		}
	};

	template <typename T, typename Allocate>
	class TLoopBase
	{
	public:
		typedef Allocate allocatorType;
		allocatorType getAllocator() const
		{
			return allocatorType();
		}

		TLoopBase(const allocatorType&)
		{
		}
		~TLoopBase()
		{
			clear();
		}

		void clear()
		{
			if (nullptr != mpNode)
			{
				_Loop_node<T>* __cur = (_Loop_node<T>*) mpNode->pNext;
				while (__cur != mpNode)
				{
					_Loop_node<T>* __tmp = __cur;
					__cur = (_Loop_node<T>*) __cur->pNext;
					_Destroy(&__tmp->Data);
					_M_put_node(__tmp);
				}
				mpNode = nullptr;
			}
		}

	protected:
		typedef TAllocator<_Loop_node<T> > _Alloc_type;

		void _M_put_node(_Loop_node<T>* pNode)
		{
			_Alloc_type::deallocate(pNode, 1);
		}

		_Loop_node<T>* _M_get_node()
		{
			return _Alloc_type::allocate(1);
		}

	public:
		_Loop_node<T>* mpNode = nullptr;
	};

	template< typename T, typename Allocate = TAllocator<T> >
	class TLoop : protected TLoopBase<T, Allocate>
	{
	private:
		typedef TLoopBase<T, Allocate> _Base;

	protected:
		typedef void* voidPointer;
	public:
		typedef T value_type;
		typedef value_type* pointer;
		typedef const value_type* const_pointer;
		typedef value_type& reference;
		typedef const value_type& const_reference;
		typedef size_t size_type;
		typedef ptrdiff_t difference_type;
		typedef _Loop_node<T> _Node;

		typedef typename _Base::_Alloc_type				allocatorType;
		typedef _Loop_iterator<T, T&, T*>				iterator;
		typedef _Loop_iterator<T, const T&, const T*>	const_iterator;
	public:
		TLoop(const Allocate& a = Allocate()) : _Base(a) {};
		~TLoop() {};
		allocatorType getAllocator() const
		{
			return _Base::getAllocator();
		}

		void resize(int size)
		{
			
		}

		void clear()
		{
			_Base::clear(); 
		}

		int size()
		{
			typedef typename _Loop_iterator_base::difference_type difference_type;
			difference_type n = 0;
			if (nullptr != _Base::mpNode)
			{
				n = 1;
				_Loop_node_base* pEnd = dynamic_cast<_Loop_node_base*>(_Base::mpNode);
				_Loop_node_base* pBegin = _Base::mpNode->pNext;
				while (pBegin != pEnd)
				{
					pBegin = pBegin->pNext;
					++n;
				}
			}
			return n;
		}

		iterator erase(iterator position)
		{
			
		}

		iterator insert(iterator __position, const T& __x)
		{
			_Node* pTmp = createNode(__x);
			pTmp->pNext = __position.mpBaseNode->pNext;
			__position.mpBaseNode->pNext = pTmp;
			__position.mpBaseNode = pTmp;
			_Base::mpNode = pTmp;
			return pTmp;
		}

		iterator insert(iterator __position)
		{
			return insert(__position, T());
		}

		void push(const T& value)
		{
			if (nullptr != _Base::mpNode)
			{
				insert(item(), value);
			}
			else
			{
				_Node* pTmp = createNode( value );
				_Base::mpNode = pTmp;
				pTmp->pNext = pTmp;
			}
		}

		iterator item()
		{
			return (_Node*)(_Base::mpNode);
		}
		const_iterator item() const
		{
			return (_Node*)(_Base::mpNode);
		}

		reference value()
		{
			return *item();
		}

		const_reference value() const
		{
			return *item();
		}

	protected:
		typedef TAllocator<_Loop_node<T> > _Alloc_type;
		void _M_put_node(_List_node<T>* pNode)
		{
			_Alloc_type::deallocate(pNode, 1);
		}

		_Loop_node<T>* _M_get_node()
		{
			return _Alloc_type::allocate(1);
		}

	private:
		_Node* createNode(const T& __x)
		{
			_Node* pNode = _Base::_M_get_node();

			_Construct(&pNode->Data, __x);

			return pNode;
		}

		_Node* createNode()
		{
			_Node* pNode = _Base::_M_get_node();
			_Construct(&pNode->Data);
			return pNode;
		}
	};
}